package org.semanticflash.rdf.graph
{

	import com.bigflexlib.ds.container.zet.impl.owSet;
	import org.semanticflash.rdf.utils.RDFTestBase;
	import org.semanticflash.rdf.utils.RDFUtil;


	public class RDFGraphTest extends RDFTestBase
	{



		private var source1:RDFManualSource;
		private var source2:RDFManualSource;
		
		private var graph:RDFGraph;
		
		private var sabc:RDFStatement;
		private var sdbc:RDFStatement;
		private var sebc:RDFStatement;



		override public function setUp( ):void
		{
			

			source1 = new RDFManualSource( );
			source2= new RDFManualSource( );	
			graph= new RDFGraph( RDFUtil.compareIRIsBasedOnTheirStringForm );

			// get a hold of some statements
			sabc = graph.getStatement( triple( "abc" ) );				
			sdbc = graph.getStatement( triple( "dbc" ) );				
			sebc = graph.getStatement( triple( "ebc" ) );				
		
		}



		override public function tearDown( ):void
		{
			source1 = null;
			source2 = null;
			graph = null;
			sabc = null;
			sdbc = null;
			sebc = null;
		}








		public function testRedirection( ):void
		{
		
			
			graph.sources.add( source1 );
			
			source1.editableTriples.add( triple("abc")  );
			source1.editableTriples.add( triple("dbc")  );

				assertTriples(  graph.triples, " abc, dbc "  );
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertFalse( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1 ] );
				assertContainersEqual( sebc.sources, [  ] );
				assertFalse( sabc.isRedirected );
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );
				


				
			graph.redirectionContext.eq(  iri("a") ,  iri("d")  );
			
				// the redirection caused a smushing ( a --> d )
				assertTriples(   graph.triples, " dbc "  );
				assertTrue( sabc.isTrue ); // both statements remain true, but one of them is redirected
				assertTrue( sdbc.isTrue );
				assertFalse( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1, sabc ] ); // <-- statement abc should appear as a source for statement dbc
				assertContainersEqual( sebc.sources, [  ] );	
				assertTrue( sabc.isRedirected );
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );				
				


			graph.redirectionContext.neq(  iri("a") ,  iri("d")  );
			
				// and we are back
				assertTriples(  graph.triples, " abc, dbc "  );
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertFalse( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1 ] );
				assertContainersEqual( sebc.sources, [  ] );
				assertFalse( sabc.isRedirected );
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );					
				
				
				

			
			// now we will try a redirection on a term that is not occurring.
			// we will add a triple with the term later

			graph.redirectionContext.eq(  iri("a") ,  iri("e")  );
			
				// this shouldn't change the size								
				assertEquals(  graph.triples.size, 2  );
				// but we should see a new, different triple
				assertTriples(  graph.triples, " ebc, dbc "  );
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertTrue( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1 ] );
				assertContainersEqual( sebc.sources, [ sabc ] ); // <-- the only source for ebc is the redirection of abc
				assertTrue( sabc.isRedirected );
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );					
				
				
				
				
			source1.editableTriples.add( triple("ebc") );
			
				assertTriples(  graph.triples, " ebc, dbc "  ); // no visible changes, since ebc was already stated
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertTrue( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1 ] );
				assertContainersEqual( sebc.sources, [ sabc, source1 ] ); // <-- now we have a new source
				assertTrue( sabc.isRedirected );
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );					
				
				
			
			
			
			graph.redirectionContext.eq( iri("a"), iri("d") );			
						
				assertTriples(  graph.triples, " ebc "  ); 
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertTrue( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1 ] );
				assertContainersEqual( sebc.sources, [ sabc, sdbc, source1 ] ); // sdbc is now a source for ebc as well
				assertTrue( sabc.isRedirected );
				assertTrue( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );	





			graph.redirectionContext.neq( iri("a"), iri("e") );			
						
				assertTriples(  graph.triples, " ebc, dbc "  ); 
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertTrue( sebc.isTrue );
				assertContainersEqual( sabc.sources, [ source1 ] );
				assertContainersEqual( sdbc.sources, [ source1, sabc ] );
				assertContainersEqual( sebc.sources, [ source1 ] );
				assertTrue( sabc.isRedirected );
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );	


			graph.sources.clear( );
			
				assertTriples(  graph.triples, "  "  ); 
				assertFalse( sabc.isTrue );
				assertFalse( sdbc.isTrue );
				assertFalse( sebc.isTrue );
				assertContainersEqual( sabc.sources, [  ] );
				assertContainersEqual( sdbc.sources, [  ] );
				assertContainersEqual( sebc.sources, [  ] );
				assertTrue( sabc.isRedirected ); // this is still redirected
				assertFalse( sdbc.isRedirected );
				assertFalse( sebc.isRedirected );				
			
			
		
		
		}

		
		private function fyi( msg:* ):void
		{
			// trace( msg );		
		}



		/**
		 * 
		 * TODO: update this method to use  assertContainersEqual() and assertTriples()
		 * Not necessary, but makes things more readable
		 * 
		 */
		public function testSimpleAddAndRemove( ):void
		{


				// the graph starts empty			
				assertEquals( graph.sources.size, 0 );
				assertEquals( graph.triples.size, 0 );


			// add the source
			graph.sources.add( source1 );
			
			
			source1.editableTriples.add( triple( "abc" ) );			
			
				// there is one published triple now
				assertEquals( graph.triples.size, 1 );
			
			source1.editableTriples.add( triple( "dbc" ) );			
			
				assertEquals( graph.triples.size, 2 );
				
				// some statements should be true
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertFalse( sebc.isTrue );
			
				// only one source should be supporting them
				assertEquals( sabc.sources.size, 1 );								
				assertEquals( sdbc.sources.size, 1 );								
				assertEquals( sebc.sources.size, 0 );								
				
				// it should be equal to "source"
				assertTrue( sabc.sources.contains( source1 ) );
				assertTrue( sdbc.sources.contains( source1 ) );
				
								
			// we add a second source that will support abc and dbc ( not dbc )
			

			
			// we wil preload this source
			source2.editableTriples.add( triple("abc") );
			source2.editableTriples.add( triple("ebc") );
		

			graph.sources.add( source2 );		
		
				// there are three published triples now
				assertEquals( graph.triples.size, 3 );		
								
				assertTriples( graph.triples, " abc, dbc, ebc " )
				
				
				//assertTrue(  compareTriples( graph.triples, " abc, dbc, ebc " )  );
						
				// all statements are true
				assertTrue( sabc.isTrue );
				assertTrue( sdbc.isTrue );
				assertTrue( sebc.isTrue );
			
				// check sources
				assertEquals( sabc.sources.size, 2 );								
				assertEquals( sdbc.sources.size, 1 );								
				assertEquals( sebc.sources.size, 1 );								
				
				// check the actual sources in the statements
				assertTrue( sabc.sources.compare( owSet( [ source1, source2 ] ) ).isEqual   );
				assertTrue( sdbc.sources.compare( owSet( [ source1 ] ) ).isEqual   );
				assertTrue( sebc.sources.compare( owSet( [ source2 ] ) ).isEqual   );
		
			
			
			// remove source1
			graph.sources.remove( source1 );
			

				assertTrue(  compareTriples( graph.triples, " abc, ebc " )  );
						
				assertTrue( sabc.isTrue );
				assertFalse( sdbc.isTrue );
				assertTrue( sebc.isTrue );
			
				assertEquals( sabc.sources.size, 1 );								
				assertEquals( sdbc.sources.size, 0 );								
				assertEquals( sebc.sources.size, 1 );								
				
				assertTrue( sabc.sources.compare( owSet( [ source2 ] ) ).isEqual   );
				assertTrue( sebc.sources.compare( owSet( [ source2 ] ) ).isEqual   );				
				
			
			
					
		
		
		
		}


		
		
		
		
		
		
	}
	

}